<?php
#error_reporting(E_ALL);
# import core libs
include dirname(__FILE__) . '/Core.php';
include dirname(__FILE__) . '/../config/config.conf.php';
include_once dirname(__FILE__) . '/Statistic.inc.php';
include_once dirname(__FILE__) . '/../SDOServiceErrorCode.php';
sdk_import('@.libraries.SDK_Log');
class ServiceBase
{
    const DEFAULT_CONNECTION_TIME_OUT = 5;
    # Log OBJ
    protected static $logger = NULL;
    # SOAP静态对象
    protected static $soapList = array();
    protected static $errNo = 0;
    protected static $errMsg = '';
    const ERROR_KEY_GLUE = ": ";
    const ERROR_SEPERATE_GLUE = "\t";
    /**
     * 获取soap对象引用
     * 
     * @param string $wsdl 目标地址
     * @param array $options 参数数组
     * @return mixed
     */
    public static function getSoapInc ($wsdl, $options = array(), &$message)
    {
        if (self::$errNo) {
        	self::$errNo = 0;
        }
        $key = md5($wsdl);
        if (! isset(self::$soapList[$key])) {
            if (! self::curlTest(array(
                $wsdl
            ))) {
                $message = "不能连接到服务 ";
                self::setErrNo(SDOServiceErrorCode::API_EC_SERVICE);
                return false;
            }
            if (! is_array($options)) {
                $options = array();
            }
            if (empty($options['connection_timeout'])) {
                $options['connection_timeout'] = self::DEFAULT_CONNECTION_TIME_OUT;
            }
            try {
                self::$soapList[$key] = new SoapClient($wsdl, $options);
            } catch (SoapFault $fault) {
                $message = $fault->getMessage() . "||" . $fault->faultcode;
                self::setErrNo(SDOServiceErrorCode::API_EC_SERVICE);
                return FALSE;
            }
        }
        return self::$soapList[$key];
    }
    /**
     * 发送soap请求 适合单参数的调用
     * 
     * @param string $apiName 方法名称
     * @param array $apiParam 参数
     * @param string $wsdl
     * @param array $options
     * @param string $message
     * 
     * @return 
     */
    protected static function soapRequest ($apiName, $apiParam, $wsdl, $options = array(), &$message)
    {
        if (! is_array($options)) {
            $options = array();
        }
        try {
            $soap = self::getSoapInc($wsdl, $options, $message);
            if ($soap === FALSE) {
                return FALSE;
            }
            $result = $soap->$apiName($apiParam);
        } catch (SoapFault $e) {
            $message = $e->getMessage();
            self::setErrNo(SDOServiceErrorCode::API_EC_UNKNOWN);
            return FALSE;
        }
        return $result;
    }
    /**
     * Get Restful Interface Content
     *
     * @param string $url
     * @param string $message
     * @return boolean
     */
    protected static function getRestfulContent ($url, &$message)
    {
        if (self::$errNo) {
        	self::$errNo = 0;
        }
        sdk_import('&.util.http.Request');
        $tmpUrl = explode("?", $url);
//        if (! self::curlTest(array(
//            $tmpUrl[0]
//        ))) {
//            $message = "不能连接到服务 ";
//            self::setErrNo(SDOServiceErrorCode::API_EC_SERVICE);
//            return false;
//        }
        $result = Request::getContent($url, $message);
        if ($result===false) {
        	$message = "http-code: {$message['http_code']}, 不能连接到服务";
        	self::setErrNo(SDOServiceErrorCode::API_EC_SERVICE);
        }
        return $result;
    }
    /**
	 * curl 方式请求
	 * 
	 * @param String $url 请求网址
	 * @param String $postString 要post的参数 格式如  xxx=1&yyy=2
	 * @param Array $option 参数 如 array(CURLOPT_REFERER=>'http://www.51.com/',CURLOPT_HTTPHEADER=>array('Host: client.sdo.com'))
	 * @return 
	 */
	protected static function curlPost ( $url, $postString = '', &$message )
	{
		$ch = curl_init(); // 初始化CURL句柄
		curl_setopt( $ch, CURLOPT_URL, $url ); //设置请求的URL
		curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); // 设为TRUE把curl_exec()结果转化为字串，而不是直接输出
		curl_setopt( $ch, CURLOPT_POST, 1 ); //启用POST提交
		curl_setopt( $ch, CURLOPT_POSTFIELDS, $postString ); //设置POST提交的字符串  
		curl_setopt($ch, CURLOPT_TIMEOUT, self::DEFAULT_CONNECTION_TIME_OUT);
		// curl_setopt($ch, CURLOPT_PORT, 80); //设置端口
		$timeout = 25;
		if(strstr($postString, "accountCheckReport")){
		    $timeout = 80;
		}
		curl_setopt( $ch, CURLOPT_TIMEOUT, $timeout ); // 超时时间
		$data = curl_exec( $ch ); //执行预定义的CURL
		$info = curl_getinfo( $ch ); //得到返回信息的特性
		if ( $info['http_code'] != "200" ) {
			$message = "不能连接到服务";
			curl_close( $ch );
			return false;
		} 
		curl_close( $ch );
		return $data;
	} 
    /**
     * write log
     *
     * @param string $s
     * @param string $server
     */
    protected static function log ($s, $server, $success = false)
    {
        if (SDK_LOG_INFO) {
            if (! isset(self::$logger[$server]) || ! (self::$logger[$server] instanceof Logger)) {
                self::$logger[$server] = &SDK_Log::getLogInstance($server);
            }            
            if (! $success || ($success && LOG_SUCCESS)) {
                
                self::$logger[$server]->info(buildErr($s));
            }
        }
    }
    /**
     * write warn log
     *
     * @param string $s
     * @param string $server
     */
    protected static function warn ($s, $server)
    {
        if (! isset(self::$logger[$server]) || ! (self::$logger[$server] instanceof Logger)) {
            self::$logger[$server] = &SDK_Log::getLogInstance($server);
        }
        self::$logger[$server]->warn(buildErr($s));
    }
    /**
     * write fatal log
     *
     * @param string $s
     * @param string $server
     */
    protected static function fatal ($s, $server)
    {
        if (! isset(self::$logger[$server]) || ! (self::$logger[$server] instanceof Logger)) {
            self::$logger[$server] = &SDK_Log::getLogInstance($server);
        }
        if (defined("SDK_ALARM") && SDK_ALARM) {
            sdk_assert($s, $server, 'FATAL');
        }
        self::$logger[$server]->fatal(buildErr($s));
    }
    /**
     * write error log
     *
     * @param string $s
     * @param string $server
     */
    protected static function error ($s, $server)
    {
        if (! isset(self::$logger[$server]) || ! (self::$logger[$server] instanceof Logger)) {
            self::$logger[$server] = &SDK_Log::getLogInstance($server);
        }
        if (defined("SDK_ALARM") && SDK_ALARM) {
            sdk_assert($s, $server, 'ERROR');
        }
        self::$logger[$server]->error(buildErr($s));
    }
    /**
     * 验证传递参数合法
     *
     * @param array $array
     * @param array $keys
     * @param string $message
     * @return Boolean
     */
    protected static function _validateParam ($array, $keys, &$message)
    {
        if (is_array($keys)) {
            foreach ($keys as $item) {
                if (! isset($array[$item])) {
                    $message = "缺少 {$item} 参数";
                    return FALSE;
                }
            }
        }
        return TRUE;
    }
    protected static function curlTest ($urlList, $rep = null)
    {
        foreach ($urlList as $url) {
            if (! $url) {
                break;
            }
            $userAgent = false;
            if (! strstr($url, "http://")) {
                $re = "/soap:address location=\"([^\"]+)\"/i";
                preg_match_all($re, file_get_contents($url), $arr);
                if ($rep) {
                    $url = strtr($arr[1][0], $rep);
                } else {
                    $url = $arr[1][0] . "?WSDL";
                }
                $userAgent = true;
            }
            $urlInfo = parse_url($url);
            if (! isset($urlInfo['port'])) {
                $urlInfo['port'] = 80;
            }
            $t = microtime(true);
            $fp = fsockopen($urlInfo['host'], $urlInfo['port'], $errno, $errstr, 10);
            if (! $fp) {
                $msg = "URL: " . $url . "||errno-" . $errno . "-err-" .
                     $errstr . "||total: " . (microtime(
                    true) - $t);
                writePingLog($errno, $msg);
                return false;
            } else {
                $path = $urlInfo['path'];
                if (isset($urlInfo['query']) && $urlInfo['query']) {
                    $path .= "?" . $urlInfo['query'];
                }
                $out = "GET {$path} HTTP/1.1\r\n";
                $out .= "Host: {$urlInfo['host']}\r\n";
                $out .= "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n";
                $out .= "Connection: Close\r\n\r\n";
                //echo $out."<br>";
                fwrite($fp, $out);
                $result = fgets($fp, 128);
                $metaInfo = stream_get_meta_data($fp);                
                fclose($fp);
                if (! strstr($result, "200 OK")) {                    
                    $errno = SDOServiceErrorCode::API_EC_SERVICE;
                    if ($metaInfo['timed_out']) {
                    	$errno = SDOServiceErrorCode::API_EC_TIMEOUT;
                    	$result = SDOServiceErrorCode::getMessage($errno);
                    }
                    $msg = "URL: " . $url . "||err:" .
                     $result . "||total: " . (microtime(
                    true) - $t);
                    self::setErr($errno, $msg);
                    writePingLog($msg);
                    
                    return false;
                }
            }
            
        }
        return true;
    }
    protected static function setErrNo($errNo)
    {
        self::$errNo = $errNo;
    }
    protected static function setErr($errNo, $errMsg)
    {
        self::$errNo = $errNo;
        self::$errMsg = $errMsg;
    }
    
    public static function getErrNo()
    {
        return self::$errNo;
    }
    public static function getErrMsg()
    {
        return self::$errMsg;
    }
    
}